home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / OBJNAM.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  41KB  |  1,668 lines

  1. /*    SCCS Id: @(#)objnam.c    3.0    89/11/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6. #ifdef TUTTI_FRUTTI
  7. #include <ctype.h>    /* for isalpha() */
  8. #endif
  9.  
  10. /* "an uncursed partly eaten guardian naga hatchling corpse" */
  11. #define    PREFIX    50
  12. #define SCHAR_MAX 127
  13.  
  14. #ifndef OVLB
  15.  
  16. STATIC_DCL const char *keystr[N_LOX], *lockstr[N_LOX];
  17.  
  18. #else /* OVLB */
  19. /*    We want the player to be able to learn what key goes in what lock.  */
  20. STATIC_OVL const char NEARDATA *keystr[N_LOX] = { "round", "square", "triangular", "oval",
  21.                           "octagonal", "hexagonal", "cylindrical",
  22.                           "irregular", "conical", "wedge-shaped" },
  23.              NEARDATA *lockstr[N_LOX] = { "round", "square", "triangular", "oval",
  24.                           "octagonal", "hexagonal", "wide",
  25.                           "notched", "large round", "large square" };
  26. #endif /* OVLB */
  27.  
  28. STATIC_DCL int FDECL(named_key,(const char *));
  29. STATIC_DCL int FDECL(named_box,(const char *));
  30. STATIC_DCL char *FDECL(strprepend,(char *,const char *));
  31.  
  32. #ifdef OVL1
  33. static char *FDECL(sitoa,(int));
  34. #endif /* OVL1 */
  35.  
  36. struct Jitem {
  37.     int item;
  38.     const char *name;
  39. };
  40.  
  41. #ifndef OVLB
  42.  
  43. STATIC_DCL struct Jitem Japanese_items[];
  44.  
  45. #else /* OVLB */
  46.  
  47. STATIC_OVL struct Jitem Japanese_items[] = {
  48.     { SHORT_SWORD, "wakizashi" },
  49.     { BROADSWORD, "ninja-to" },
  50.     { GLAIVE, "naginata" },
  51.     /* { BOW, "yumi" }, */
  52.     { LOCK_PICK, "osaku" },
  53.     {0, "" }
  54. };
  55.  
  56. #endif /* OVLB */
  57.  
  58. STATIC_DCL const char *FDECL(Japanese_item_name,(int));
  59.  
  60. #ifdef OVL1
  61.  
  62. STATIC_OVL int
  63. named_key(s) register const char *s; {
  64.     char tc[BUFSZ];
  65.     register int i;
  66.  
  67.     for(i=0; i<10; i++) {
  68.         Strcpy(tc, keystr[i]);
  69.         Strcat(tc, " key");
  70.         if(!strcmp(s,tc)) return(i+1);
  71.     }
  72.     return(0);
  73. }
  74.  
  75. STATIC_OVL int
  76. named_box(s)
  77. register const char *s;
  78. {
  79.     char tc[BUFSZ];
  80.     register int i;
  81.  
  82.     for(i=0; i<10; i++) {
  83.         Strcpy(tc, lockstr[i]);
  84.         Strcat(tc, " keyhole)");
  85.         if(!strcmp(s,tc)) return(i+1);
  86.     }
  87.     return(0);
  88. }
  89.  
  90. STATIC_OVL char *
  91. strprepend(s,pref)
  92. register char *s;
  93. register const char *pref; {
  94. register int i = strlen(pref);
  95.     if(i > PREFIX) {
  96.         pline("WARNING: prefix too short.");
  97.         return(s);
  98.     }
  99.     s -= i;
  100.     (void) strncpy(s, pref, i);    /* do not copy trailing 0 */
  101.     return(s);
  102. }
  103.  
  104. static char *
  105. sitoa(a) int a; {
  106. #ifdef LINT    /* static char buf[13]; */
  107.     char buf[13];
  108. #else
  109.     static char NEARDATA buf[13];
  110. #endif
  111.     Sprintf(buf, (a < 0) ? "%d" : "+%d", a);
  112.     return(buf);
  113. }
  114.  
  115. #endif /* OVL1 */
  116. #ifdef OVLB
  117.  
  118. char *
  119. typename(otyp)
  120. register int otyp;
  121. {
  122. #ifdef LINT    /* static char buf[BUFSZ]; */
  123. char buf[BUFSZ];
  124. #else
  125. static char NEARDATA buf[BUFSZ];
  126. #endif
  127. register struct objclass *ocl = &objects[otyp];
  128. register const char *actualn = ocl->oc_name;
  129. register const char *dn = ocl->oc_descr;
  130. register const char *un = ocl->oc_uname;
  131. register int nn = ocl->oc_name_known;
  132.  
  133.     if (pl_character[0] == 'S' && Japanese_item_name(otyp))
  134.         actualn = Japanese_item_name(otyp);
  135.     switch(ocl->oc_olet) {
  136.     case POTION_SYM:
  137.         Strcpy(buf, "potion");
  138.         break;
  139.     case SCROLL_SYM:
  140.         Strcpy(buf, "scroll");
  141.         break;
  142.     case WAND_SYM:
  143.         Strcpy(buf, "wand");
  144.         break;
  145. #ifdef SPELLS
  146.     case SPBOOK_SYM:
  147.         Strcpy(buf, "spellbook");
  148.         break;
  149. #endif
  150.     case RING_SYM:
  151.         Strcpy(buf, "ring");
  152.         break;
  153.     case AMULET_SYM:
  154.         if(nn)
  155.             Strcpy(buf,actualn);
  156.         else
  157.             Strcpy(buf,"amulet");
  158.         if(un)
  159.             Sprintf(eos(buf)," called %s",un);
  160.         if(dn)
  161.             Sprintf(eos(buf)," (%s)",dn);
  162.         return(buf);
  163.     default:
  164.         if(nn) {
  165.             Strcpy(buf, actualn);
  166.             if(otyp >= TURQUOISE && otyp <= JADE)
  167.                 Strcat(buf, " stone");
  168.             if(un)
  169.                 Sprintf(eos(buf), " called %s", un);
  170.             if(dn)
  171.                 Sprintf(eos(buf), " (%s)", dn);
  172.         } else {
  173.             Strcpy(buf, dn ? dn : actualn);
  174.             if(ocl->oc_olet == GEM_SYM) {
  175.                 if (otyp == LOADSTONE || otyp == LUCKSTONE)
  176.                     Strcat(buf, " stone");
  177.                 else
  178.                     Strcat(buf, " gem");
  179.             }
  180.             if(un)
  181.                 Sprintf(eos(buf), " called %s", un);
  182.         }
  183.         return(buf);
  184.     }
  185.     /* here for ring/scroll/potion/wand */
  186.     if(nn)
  187.         Sprintf(eos(buf), " of %s", actualn);
  188.     if(un)
  189.         Sprintf(eos(buf), " called %s", un);
  190.     if(dn)
  191.         Sprintf(eos(buf), " (%s)", dn);
  192.     return(buf);
  193. }
  194.  
  195. /* Give the name of an object seen at a distance.  Unlike xname/doname,
  196.  * we don't want to set dknown if it's not set already.  The kludge used is
  197.  * to temporarily set Blind so that xname() skips the dknown setting.  This
  198.  * assumes that we don't want to do this too often; if this function becomes
  199.  * frequently used, it'd probably be better to pass a parameter to xname()
  200.  * or doname() instead.
  201.  */
  202. char *
  203. distant_name(obj, func)
  204. register struct obj *obj;
  205. char *FDECL((*func), (struct obj *));
  206. {
  207.     char *str;
  208.  
  209.     long save_Blinded = Blinded;
  210.     Blinded = 1;
  211.     str = (*func)(obj);
  212.     Blinded = save_Blinded;
  213.     return str;
  214. }
  215.  
  216. #endif /* OVLB */
  217. #ifdef OVL1
  218.  
  219. char *
  220. xname(obj)
  221. register struct obj *obj;
  222. {
  223. #ifdef LINT    /* lint may handle static decl poorly -- static char bufr[]; */
  224. char bufr[BUFSZ];
  225. #else
  226. static char bufr[BUFSZ];
  227. #endif
  228. register char *buf = &(bufr[PREFIX]);    /* leave room for "17 -3 " */
  229. register int nn = objects[obj->otyp].oc_name_known;
  230. register const char *actualn = objects[obj->otyp].oc_name;
  231. register const char *dn = objects[obj->otyp].oc_descr;
  232. register const char *un = objects[obj->otyp].oc_uname;
  233.  
  234.     if (pl_character[0] == 'S' && Japanese_item_name((int)obj->otyp))
  235.         actualn = Japanese_item_name((int)obj->otyp);
  236.  
  237.     buf[0] = 0;
  238.     if(!Blind) obj->dknown=1;
  239.     switch(obj->olet) {
  240.         case AMULET_SYM:
  241.         if(obj->otyp == AMULET_OF_YENDOR) {
  242.             Strcpy(buf, (obj->spe < 0 && obj->known) ?
  243.                "cheap plastic imitation of the " : "");
  244.             Strcat(buf, actualn);
  245.         } else if (!obj->dknown)
  246.             Strcpy(buf, "amulet");
  247.         else if (nn)
  248.             Strcpy(buf, actualn);
  249.         else if (un)
  250.             Sprintf(buf,"amulet called %s", un);
  251.         else
  252.             Sprintf(buf,"%s amulet", dn);
  253.         break;
  254.         case WEAPON_SYM:
  255.         if(obj->otyp <= SHURIKEN && obj->opoisoned)
  256.             Strcpy(buf, "poisoned ");
  257.         case VENOM_SYM:
  258.         case TOOL_SYM:
  259.         if(un) {
  260.             /* un must come first here.  If it does not, they could
  261.              * tell objects apart by seeing which ones refuse to
  262.              * accept names.
  263.              */
  264.             Sprintf(buf, "%s called %s",
  265.                 nn ? actualn : dn, un);
  266.         } else if(nn)
  267.             Strcat(buf, actualn);
  268.         else
  269.             Strcat(buf, dn);
  270.         /* If we use an() here we'd have to remember never to use */
  271.         /* it whenever calling doname() or xname(). */
  272.         if(obj->otyp == FIGURINE)
  273.             Sprintf(eos(buf), " of a%s %s",
  274.             index(vowels,*(mons[obj->corpsenm].mname)) ? "n" : "",
  275.             mons[obj->corpsenm].mname);
  276.         break;
  277.         case ARMOR_SYM:
  278.         if(obj->otyp==DRAGON_SCALE_MAIL) {
  279.             Sprintf(buf, "%s scale mail",
  280.                         mons[obj->corpsenm].mname);
  281.             break;
  282.         }
  283.  
  284.         if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
  285.  
  286.         if(nn)    Strcat(buf, actualn);
  287.         else if(un) {
  288.             if(is_boots(obj))
  289.                 Strcat(buf,"boots");
  290.             else if(is_gloves(obj))
  291.                 Strcat(buf,"gloves");
  292.             else if(is_cloak(obj))
  293.                 Strcpy(buf,"cloak");
  294.             else if(is_helmet(obj))
  295.                 Strcpy(buf,"helmet");
  296.             else if(is_shield(obj))
  297.                 Strcpy(buf,"shield");
  298.             else
  299.                 Strcpy(buf,"armor");
  300.             Strcat(buf, " called ");
  301.             Strcat(buf, un);
  302.         } else    Strcat(buf, dn);
  303.         break;
  304.         case FOOD_SYM:
  305. #ifdef TUTTI_FRUTTI
  306.         if (obj->otyp == SLIME_MOLD) {
  307.             register struct fruit *f;
  308.  
  309.             for(f=ffruit; f; f = f->nextf) {
  310.                 if(f->fid == obj->spe) {
  311.                     Strcpy(buf, f->fname);
  312.                     break;
  313.                 }
  314.             }
  315.             if (!f) impossible("Bad fruit #%d?", obj->spe);
  316.             break;
  317.         }
  318. #endif
  319.         Strcpy(buf, actualn);
  320.         if(obj->otyp == TIN && obj->known) {
  321.             if(obj->spe > 0)
  322.             Strcat(buf, " of spinach");
  323.             else if (mons[obj->corpsenm].mlet == S_FUNGUS)
  324.             Sprintf(eos(buf), " of %s", mons[obj->corpsenm].mname);
  325.             else if(obj->corpsenm >= 0)
  326.             Sprintf(eos(buf), " of %s meat", mons[obj->corpsenm].mname);
  327.             else Strcpy(buf, "empty tin");
  328.         }
  329.         break;
  330.         case CHAIN_SYM:
  331.         Strcpy(buf, actualn);
  332.         break;
  333.         case ROCK_SYM:
  334.         if(obj->otyp == STATUE)
  335.             Sprintf(buf, "%s of a%s %s", actualn,
  336.             index(vowels,*(mons[obj->corpsenm].mname)) ? "n" : "",
  337.             mons[obj->corpsenm].mname);
  338.         else Strcpy(buf, actualn);
  339.         break;
  340.         case BALL_SYM:
  341.         Sprintf(buf, "%sheavy iron ball",
  342.           (obj->owt > objects[obj->otyp].oc_weight) ? "very " : "");
  343.         break;
  344.         case POTION_SYM:
  345.         if(nn || un || !obj->dknown) {
  346.             Strcpy(buf, "potion");
  347.             if(!obj->dknown) break;
  348.             if(nn) {
  349.                 Strcat(buf, " of ");
  350.                 if(obj->otyp == POT_WATER &&
  351.                    objects[POT_WATER].oc_name_known &&
  352.                    (obj->bknown || pl_character[0] == 'P') &&
  353.                    (obj->blessed || obj->cursed)) {
  354.                 Strcat(buf, obj->blessed ? "holy " : "unholy ");
  355.                 }
  356.                 Strcat(buf, actualn);
  357.             } else {
  358.                 Strcat(buf, " called ");
  359.                 Strcat(buf, un);
  360.             }
  361.         } else {
  362.             Strcpy(buf, dn);
  363.             Strcat(buf, " potion");
  364.         }
  365.         break;
  366.     case SCROLL_SYM:
  367.         Strcpy(buf, "scroll");
  368.         if(!obj->dknown) break;
  369.         if(nn) {
  370.             Strcat(buf, " of ");
  371.             Strcat(buf, actualn);
  372.         } else if(un) {
  373.             Strcat(buf, " called ");
  374.             Strcat(buf, un);
  375.         } else {
  376.             Strcat(buf, " labeled ");
  377.             Strcat(buf, dn);
  378.         }
  379.         break;
  380.     case WAND_SYM:
  381.         if(!obj->dknown)
  382.             Sprintf(buf, "wand");
  383.         else if(nn)
  384.             Sprintf(buf, "wand of %s", actualn);
  385.         else if(un)
  386.             Sprintf(buf, "wand called %s", un);
  387.         else
  388.             Sprintf(buf, "%s wand", dn);
  389.         break;
  390. #ifdef SPELLS
  391.     case SPBOOK_SYM:
  392.         if(!obj->dknown)
  393.             Sprintf(buf, "spellbook");
  394.         else if(nn)
  395.             Sprintf(buf, "spellbook of %s", actualn);
  396.         else if(un)
  397.             Sprintf(buf, "spellbook called %s", un);
  398.         else
  399.             Sprintf(buf, "%s spellbook", dn);
  400.         break;
  401. #endif
  402.     case RING_SYM:
  403.         if(!obj->dknown)
  404.             Sprintf(buf, "ring");
  405.         else if(nn)
  406.             Sprintf(buf, "ring of %s", actualn);
  407.         else if(un)
  408.             Sprintf(buf, "ring called %s", un);
  409.         else
  410.             Sprintf(buf, "%s ring", dn);
  411.         break;
  412.     case GEM_SYM:
  413.         if(!obj->dknown) {
  414.             if (obj->otyp == ROCK || obj->otyp == LOADSTONE
  415.                     || obj->otyp == LUCKSTONE)
  416.                 Strcpy(buf, "stone");
  417.             else
  418.                 Strcpy(buf, "gem");
  419.             break;
  420.         }
  421.         if(!nn) {
  422.             const char *rock=
  423.     (obj->otyp==LOADSTONE||obj->otyp==LUCKSTONE) ? "stone" : "gem";
  424.             if(un)    Sprintf(buf,"%s called %s", rock, un);
  425.             else    Sprintf(buf, "%s %s", dn, rock);
  426.             break;
  427.         }
  428.         Strcpy(buf, actualn);
  429.         if(obj->otyp >= TURQUOISE && obj->otyp <= JADE)
  430.             Strcat(buf, " stone");
  431.         break;
  432.     default:
  433.         Sprintf(buf,"glorkum %c (0%o) %u %d",
  434.             obj->olet,obj->olet,obj->otyp,obj->spe);
  435.     }
  436.     if(obj->quan != 1) Strcpy(buf, makeplural(buf));
  437.  
  438.     if(obj->onamelth) {
  439.         Strcat(buf, " named ");
  440.         Strcat(buf, ONAME(obj));
  441.     }
  442.     return(buf);
  443. }
  444.  
  445. #endif /* OVL1 */
  446. #ifdef OVL0
  447.  
  448. char *
  449. doname(obj)
  450. register struct obj *obj;
  451. {
  452.     boolean ispoisoned = FALSE;
  453.     char prefix[PREFIX];
  454.     char tmpbuf[PREFIX+1];
  455.     /* when we have to add something at the start of prefix instead of the
  456.      * end (Strcat is used on the end)
  457.      */
  458.     register char *bp = xname(obj);
  459.     /* When using xname, we want "poisoned arrow", and when using
  460.      * doname, we want "poisoned +0 arrow".  This kludge is about the only
  461.      * way to do it, at least until someone overhauls xname() and doname(),
  462.      * combining both into one function taking a parameter.
  463.      */
  464.     if (!strncmp(bp, "poisoned ", 9)) {
  465.         bp += 9;
  466.         ispoisoned = TRUE;
  467.     }
  468.  
  469.     if(obj->quan != 1)
  470.         Sprintf(prefix, "%u ", obj->quan);
  471.     else
  472.         Strcpy(prefix, "a ");
  473.     if((obj->bknown || pl_character[0] == 'P') &&
  474.         (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
  475.         || (!obj->cursed && !obj->blessed))) {
  476.         /* allow 'blessed clear potion' if we don't know it's holy water;
  477.          * always allow "uncursed potion of water"
  478.          */
  479.         if(obj->cursed)
  480.         Strcat(prefix, "cursed ");
  481.         else if(obj->blessed)
  482.         Strcat(prefix, "blessed ");
  483.         else if (((obj->olet != ARMOR_SYM
  484.             && obj->olet != WAND_SYM
  485.             && obj->olet != WEAPON_SYM
  486.             && ((obj->olet != TOOL_SYM &&
  487.                  obj->olet != RING_SYM) ||
  488.                  !objects[obj->otyp].oc_charged))
  489.                 || !obj->known)
  490.         /* For items with charges or +/-, knowing the +/- means that
  491.          * the item has been totally identified, and therefore there
  492.          * is no doubt as to the object being uncursed if it's
  493.          * not described as "blessed" or "cursed".
  494.          *
  495.          * If the +/- isn't known, "uncursed" must be printed to
  496.          * avoid ambiguity between an item whose curse status is
  497.          * unknown, and an item known to be uncursed.
  498.          */
  499. #ifdef MAIL
  500.             && obj->otyp != SCR_MAIL
  501. #endif
  502.             && obj->otyp != AMULET_OF_YENDOR &&
  503.             pl_character[0] != 'P')
  504.         Strcat(prefix, "uncursed ");
  505.     }
  506.     switch(obj->olet) {
  507.     case AMULET_SYM:
  508.         if(obj->otyp == AMULET_OF_YENDOR)
  509.             if(strncmp(bp, "cheap ", 6)) {
  510.             Strcpy(tmpbuf, "the ");
  511.             Strcat(tmpbuf, prefix+2); /* skip the "a " */
  512.             Strcpy(prefix, tmpbuf);
  513.             }
  514.         if(obj->owornmask & W_AMUL)
  515.             Strcat(bp, " (being worn)");
  516.         break;
  517.     case WEAPON_SYM:
  518.         if(ispoisoned)
  519.             Strcat(prefix, "poisoned ");
  520. plus:
  521.         if(obj->known) {
  522.             Strcat(prefix, sitoa(obj->spe));
  523.             Strcat(prefix, " ");
  524.         }
  525.         break;
  526.     case ARMOR_SYM:
  527.         if(obj->owornmask & W_ARMOR)
  528.             Strcat(bp, " (being worn)");
  529.         goto plus;
  530.     case TOOL_SYM:            /* temp. hack by GAN 11/18/86 */
  531.         if(obj->owornmask & W_TOOL) { /* blindfold */
  532.             Strcat(bp, " (being worn)");
  533.             break;
  534.         }
  535. #ifdef WALKIES
  536.         if(obj->otyp == LEASH && obj->leashmon != 0) {
  537.             Strcat(bp, " (in use)");
  538.             break;
  539.         }
  540. #endif
  541.         if(obj->otyp == KEY ||
  542.            (obj->otyp == SKELETON_KEY &&
  543.             !objects[obj->otyp].oc_name_known)) {
  544.             Strcat(prefix, keystr[obj->spe]);
  545.             Strcat(prefix, " ");
  546.             break;
  547.         }
  548.         if(obj->otyp == LARGE_BOX || obj->otyp == CHEST) {
  549.             Sprintf(eos(bp), " (%s keyhole)", lockstr[obj->spe]);
  550.             break;
  551.         }
  552.         if(obj->otyp == PICK_AXE || obj->otyp == UNICORN_HORN)
  553.             goto plus;
  554.         if(!objects[obj->otyp].oc_charged) break;
  555.         /* if special tool, fall through to show charges */
  556.     case WAND_SYM:
  557.         if(obj->known)
  558.             Sprintf(eos(bp), " (%d)", obj->spe);
  559.         break;
  560.     case RING_SYM:
  561.         if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
  562.         if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
  563.         if(obj->owornmask & W_RING) {
  564.             Strcat(bp, body_part(HAND));
  565.             Strcat(bp, ")");
  566.         }
  567.         if(obj->known && objects[obj->otyp].oc_charged) {
  568.             Strcat(prefix, sitoa(obj->spe));
  569.             Strcat(prefix, " ");
  570.         }
  571.         break;
  572.     case FOOD_SYM:
  573.         if(obj->oeaten)
  574.             Strcat(prefix, "partly eaten ");
  575.         if(obj->otyp == CORPSE) {
  576.             Strcat(prefix, mons[obj->corpsenm].mname);
  577.             Strcat(prefix, " ");
  578.         } else if(obj->otyp == EGG && obj->known) {
  579.             if(obj->corpsenm >= 0) {
  580.             Strcat(prefix, mons[obj->corpsenm].mname);
  581.             Strcat(prefix, " ");
  582. #ifdef POLYSELF
  583.             if (obj->spe)
  584.                 Strcat(bp, " (laid by you)");
  585. #endif
  586.             }
  587.         }
  588.         break;
  589.     case BALL_SYM:
  590.         if(obj->owornmask & W_BALL)
  591.             Strcat(bp, " (chained to you)");
  592.             break;
  593.     }
  594.  
  595.     if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
  596.         if (obj->quan != 1)
  597.             Strcat(bp, " (wielded)");
  598.         else {
  599.             Strcat(bp, " (weapon in ");
  600.             Strcat(bp, body_part(HAND));
  601.             Strcat(bp, ")");
  602.         }
  603.     }
  604.     if(obj->unpaid)
  605.         Strcat(bp, " (unpaid)");
  606.     if (!strncmp(prefix, "a ", 2) &&
  607.             index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
  608.             && (*(prefix+2) || (strncmp(bp, "uranium", 7)
  609.                 && strncmp(bp, "unicorn", 7)))) {
  610.         Strcpy(tmpbuf, prefix);
  611.         Strcpy(prefix, "an ");
  612.         Strcpy(prefix+3, tmpbuf+2);
  613.     }
  614.     bp = strprepend(bp, prefix);
  615.     return(bp);
  616. }
  617.  
  618. #endif /* OVL0 */
  619. #ifdef OVLB
  620.  
  621. /*
  622.  * Used if only one of a collection of objects is named (e.g. in eat.c).
  623.  */
  624.  
  625. char *
  626. singular(otmp, func)
  627. register struct obj *otmp;
  628. char *FDECL((*func), (struct obj *));
  629. {
  630.     unsigned savequan;
  631.     char *nam;
  632.  
  633.     /* Note: using xname for corpses will not give the monster type */
  634.     if (otmp->otyp == CORPSE && func == xname) {
  635.         static char NEARDATA buf[31];
  636.  
  637.         Sprintf(buf, "%s corpse", mons[otmp->corpsenm].mname);
  638.         return buf;
  639.     }
  640.     savequan = otmp->quan;
  641.     otmp->quan = 1;
  642.     nam = (*func)(otmp);
  643.     otmp->quan = savequan;
  644.     return nam;
  645. }
  646.  
  647. char *
  648. an(str)
  649. register const char *str;
  650. {
  651.     static char NEARDATA buf[BUFSZ];
  652.  
  653.     buf[0] = '\0';
  654.  
  655.     if (strncmp(str, "the ", 4))
  656.         if (index(vowels, *str) &&
  657.         strncmp(str, "useful", 6) &&
  658.         strncmp(str, "unicorn", 7) &&
  659.         strncmp(str, "uranium", 7))
  660.             Strcpy(buf, "an ");
  661.         else
  662.             Strcpy(buf, "a ");
  663.  
  664.     Strcat(buf, str);
  665.     return buf;
  666. }
  667.  
  668. char *
  669. An(str)
  670. const char *str;
  671. {
  672.     register char *tmp;
  673.  
  674.     tmp = an(str);
  675.     if (*tmp == 'a') *tmp = 'A';
  676.     return tmp;
  677. }
  678.  
  679. char *
  680. aobjnam(otmp,verb)
  681. register struct obj *otmp;
  682. register const char *verb;
  683. {
  684.     register char *bp = xname(otmp);
  685.     char prefix[PREFIX];
  686.  
  687.     if(otmp->quan != 1) {
  688.         Sprintf(prefix, "%u ", otmp->quan);
  689.         bp = strprepend(bp, prefix);
  690.     }
  691.  
  692.     if(verb) {
  693.         /* verb is given in plural (without trailing s) */
  694.         Strcat(bp, " ");
  695.         if(otmp->quan != 1)
  696.             Strcat(bp, verb);
  697.         else if(!strcmp(verb, "are"))
  698.             Strcat(bp, "is");
  699.         else {
  700.             Strcat(bp, verb);
  701.             Strcat(bp, "s");
  702.         }
  703.     }
  704.     return(bp);
  705. }
  706.  
  707. char *
  708. Doname2(obj)
  709. register struct obj *obj;
  710. {
  711.     register char *s = doname(obj);
  712.  
  713.     if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
  714.     return(s);
  715. }
  716.  
  717. const char *wrp[] = { "wand", "ring", "potion", "scroll", "gem", "amulet",
  718. #ifdef SPELLS
  719.         "spellbook",
  720. #endif
  721.         /* for non-specific wishes */
  722.         "weapon", "armor", "tool", "food", "comestible",
  723.           };
  724. const char wrpsym[] = {WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM, AMULET_SYM,
  725. #ifdef SPELLS
  726.          SPBOOK_SYM,
  727. #endif
  728.          WEAPON_SYM, ARMOR_SYM, TOOL_SYM, FOOD_SYM, FOOD_SYM
  729.         };
  730.  
  731. void
  732. lcase(str)
  733. register char *str;
  734. {
  735.     register char *p;
  736.     for (p = str; *p; p++)
  737.         if('A' <= *p && *p <= 'Z') *p += 'a'-'A';
  738. }
  739.  
  740. #endif /* OVLB */
  741. #ifdef OVL0
  742.  
  743. /* Plural routine; chiefly used for user-defined fruits.  We have to try to
  744.  * account for everything reasonable the player has; something unreasonable
  745.  * can still break the code.  However, it's still a lot more accurate than
  746.  * "just add an s at the end", which Rogue uses...
  747.  *
  748.  * Also used for plural monster names ("Wiped out all homunculi.")
  749.  * and body parts.
  750.  */
  751. char *
  752. makeplural(oldstr)
  753. const char *oldstr;
  754. {
  755.     register char *spot;
  756.     static char NEARDATA str[BUFSZ];
  757.     const char *excess;
  758.     int len;
  759.  
  760.     while (*oldstr==' ') oldstr++;
  761.     if (!oldstr || !*oldstr) {
  762.         impossible("plural of null?");
  763.         Strcpy(str, "s");
  764.         return str;
  765.     }
  766.     Strcpy(str, oldstr);
  767.  
  768.     /* Search for common compounds, ex. lump of royal jelly */
  769.     for(excess=(char *)0, spot=str; *spot; spot++) {
  770.         if (!strncmp(spot, " of ", 4)
  771.                 || !strncmp(spot, " labeled ", 9)
  772.                 || !strncmp(spot, " called ", 8)
  773.                 || !strncmp(spot, " named ", 7)
  774.                 || !strcmp(spot, " above") /* lurkers above */
  775.                 || !strncmp(spot, " versus ", 8)
  776. #ifdef TUTTI_FRUTTI
  777.                 || !strncmp(spot, " from ", 6)
  778.                 || !strncmp(spot, " in ", 4)
  779.                 || !strncmp(spot, " on ", 4)
  780.                 || !strncmp(spot, " a la ", 6)
  781.                 || !strncmp(spot, " with", 5)
  782.                 || !strncmp(spot, " de ", 4)
  783.                 || !strncmp(spot, " d'", 3)
  784.                 || !strncmp(spot, " du ", 4)
  785. #endif
  786.                 ) {
  787.             excess = oldstr + (int) (spot - str);
  788.             *spot = 0;
  789.             break;
  790.         }
  791.     }
  792.     spot--;
  793.     while (*spot==' ') spot--; /* Strip blanks from end */
  794.     *(spot+1) = 0;
  795.     /* Now spot is the last character of the string */
  796.  
  797.     len = strlen(str);
  798. #ifdef TUTTI_FRUTTI
  799.     /* Single letters */
  800.     if (len==1 || !isalpha(*spot)) {
  801.         Strcpy(spot+1, "'s");
  802.         goto bottom;
  803.     }
  804. #endif
  805.  
  806.     /* man/men ("Wiped out all cavemen.") */
  807.     if (len >= 3 && !strcmp(spot-2, "man") &&
  808.             (len<6 || strcmp(spot-5, "shaman")) &&
  809.             (len<5 || strcmp(spot-4, "human"))) {
  810.         *(spot-1) = 'e';
  811.         goto bottom;
  812.     }
  813.  
  814.     /* tooth/teeth */
  815.     if (len >= 5 && !strcmp(spot-4, "tooth")) {
  816.         Strcpy(spot-3, "eeth");
  817.         goto bottom;
  818.     }
  819.  
  820.     /* knife/knives, etc... */
  821.     if (!strcmp(spot-1, "fe"))
  822.         *(spot-1) = 'v';
  823.     else if (*spot == 'f')
  824.         if (index("lr", *(spot-1)) || index(vowels, *(spot-1)))
  825.             *spot = 'v';
  826.         else if (!strncmp(spot-4, "staf", 4))
  827.             Strcpy(spot-1, "ve");
  828.  
  829.     /* foot/feet (body part) */
  830.     if (len >= 4 && !strcmp(spot-3, "foot")) {
  831.         Strcpy(spot-2, "eet");
  832.         goto bottom;
  833.     }
  834.  
  835.     /* ium/ia (mycelia, baluchitheria) */
  836.     if (len >= 3 && !strcmp(spot-2, "ium")) {
  837.         *(spot--) = (char)0;
  838.         *spot = 'a';
  839.         goto bottom;
  840.     }
  841.  
  842.     /* algae, larvae, hyphae (another fungus part) */
  843. #ifdef TUTTI_FRUTTI
  844.     if ((len >= 4 && !strcmp(spot-3, "alga")) ||
  845.         (len >= 5 &&
  846.          (!strcmp(spot-4, "hypha") || !strcmp(spot-4, "larva")))) {
  847. #else
  848.     if (len >= 5 && (!strcmp(spot-4, "hypha"))) {
  849. #endif
  850.         Strcpy(spot, "ae");
  851.         goto bottom;
  852.     }
  853.  
  854.     /* fungus/fungi, homunculus/homunculi, but wumpuses */
  855.     if (!strcmp(spot-1, "us") && strcmp(spot-5, "wumpus")) {
  856.         *(spot--) = (char)0;
  857.         *spot = 'i';
  858.         goto bottom;
  859.     }
  860.  
  861.     /* vortex/vortices */
  862.     if (len >= 6 && !strcmp(spot-3, "rtex")) {
  863.         Strcpy(spot-1, "ices");
  864.         goto bottom;
  865.     }
  866.  
  867.     /* djinni/djinn (note: also efreeti/efreet) */
  868.     if (len >= 6 && !strcmp(spot-5, "djinni")) {
  869.         *(spot--) = (char)0;
  870.         goto bottom;
  871.     }
  872.  
  873.     /* same singular and plural */
  874.     /* note: also swine, trout, grouse */
  875.     if ((len >= 7 && !strcmp(spot-6, "samurai")) ||
  876.         (len >= 5 &&
  877. #ifdef TUTTI_FRUTTI
  878.          (!strcmp(spot-4, "manes") || !strcmp(spot-4, "sheep"))) ||
  879.         (len >= 4 &&
  880.          (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") ||
  881.           !strcmp(spot-3, "deer"))))
  882. #else
  883.          !strcmp(spot-4, "manes")))
  884. #endif
  885.         goto bottom;
  886.  
  887. #ifdef TUTTI_FRUTTI
  888.     /* mouse/mice,louse/lice (not a monster, but possible in a food name) */
  889.     if (len >= 5 && !strcmp(spot-3, "ouse") && index("MmLl", *(spot-4))) {
  890.         Strcpy(spot-3, "ice");
  891.         goto bottom;
  892.     }
  893.  
  894.     /* matzoh/matzot, possible food name */
  895.     if (len >= 6 && (!strcmp(spot-5, "matzoh")
  896.                     || !strcmp(spot-5, "matzah"))) {
  897.         Strcpy(spot-1, "ot");
  898.         goto bottom;
  899.     }
  900.     if (len >= 5 && (!strcmp(spot-4, "matzo")
  901.                     || !strcmp(spot-5, "matza"))) {
  902.         Strcpy(spot, "ot");
  903.         goto bottom;
  904.     }
  905.  
  906.     /* child/children (for the wise guys who give their food funny names) */
  907.     if (len >= 5 && !strcmp(spot-4, "child")) {
  908.         Strcpy(spot, "dren");
  909.         goto bottom;
  910.     }
  911.  
  912.     /* sis/ses (oasis, nemesis) */
  913.     if (len >= 3 && !strcmp(spot-2, "sis")) {
  914.         *(spot-1) = 'e';
  915.         goto bottom;
  916.     }
  917.  
  918.     /* note: -eau/-eaux (gateau, bordeau...) */
  919.     /* note: ox/oxen, VAX/VAXen, goose/geese */
  920. #endif
  921.  
  922.     /* Ends in z, x, s, ch, sh; add an "es" */
  923.     if (index("zxsv", *spot) || (*spot=='h' && index("cs", *(spot-1)))
  924. #ifdef TUTTI_FRUTTI
  925.     /* Kludge to get "tomatoes" and "potatoes" right */
  926.                 || (len >= 4 && !strcmp(spot-2, "ato"))
  927. #endif
  928.                                     ) {
  929.         Strcpy(spot+1, "es");
  930.         goto bottom;
  931.     }
  932.  
  933.     /* Ends in y preceded by consonant (note: also "qu"); change to "ies" */
  934.     if (*spot == 'y' &&
  935.         (!index(vowels, *(spot-1)))) {
  936.         Strcpy(spot, "ies");
  937.         goto bottom;
  938.     }
  939.  
  940.     /* Default: append an 's' */
  941.     Strcpy(spot+1, "s");
  942.  
  943. bottom:    if (excess) Strcpy(str+strlen(str), excess);
  944.     return str;
  945. }
  946.  
  947. #endif /* OVL0 */
  948.  
  949. struct o_range {
  950.     const char *name, osym;
  951.     int  f_o_range, l_o_range;
  952. };
  953.  
  954. #ifndef OVLB
  955.  
  956. STATIC_DCL const struct o_range o_ranges[];
  957.  
  958. #else /* OVLB */
  959.  
  960. /* wishable subranges of objects */
  961. STATIC_OVL const struct o_range NEARDATA o_ranges[] = {
  962.     { "bag",    TOOL_SYM,   SACK,        BAG_OF_TRICKS },
  963.     { "gloves",    ARMOR_SYM,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
  964.     { "gauntlets",    ARMOR_SYM,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
  965.     { "boots",    ARMOR_SYM,  LOW_BOOTS,        LEVITATION_BOOTS },
  966.     { "shoes",    ARMOR_SYM,  LOW_BOOTS,        IRON_SHOES },
  967.     { "cloak",    ARMOR_SYM,  MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
  968.     { "shield",    ARMOR_SYM,  SMALL_SHIELD,   SHIELD_OF_REFLECTION },
  969. #ifdef TOLKIEN    /* note: "helmet" is a specific item */
  970.     { "helm",    ARMOR_SYM,  ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
  971. #else
  972.     { "helm",    ARMOR_SYM,  ORCISH_HELM,    HELM_OF_TELEPATHY },
  973. #endif
  974.     { "sword",    WEAPON_SYM, SHORT_SWORD,    KATANA }
  975. };
  976.  
  977. /*
  978.  * Singularize a string the user typed in; this helps reduce the complexity
  979.  * of readobjnam, and is also used in pager.c to singularize the string
  980.  * for which help is sought.
  981.  */
  982.  
  983. char *
  984. makesingular(oldstr)
  985. const char *oldstr;
  986. {
  987.     char *p, *bp;
  988.     static char NEARDATA str[BUFSZ];
  989.  
  990.     if (!oldstr || !*oldstr) {
  991.         impossible("singular of null?");
  992.         str[0] = 0; return str;
  993.     }
  994.     Strcpy(str, oldstr);
  995.     bp = str;
  996.  
  997.     while (*bp == ' ') bp++;
  998.     /* find "cloves of garlic", "worthless pieces of blue glass" */
  999.     for(p = bp; *p; p++) 
  1000.         if(!strncmp(p, "s of ", 5)){
  1001.         /* but don't singularize "gauntlets" */
  1002.         if(strncmp(p-8, "gauntlet", 8))
  1003.             while(*p = p[1]) p++;
  1004.         return bp;
  1005.         }
  1006.  
  1007.     /* remove -s or -es (boxes) or -ies (rubies) */
  1008.     p = eos(bp);
  1009.     if(p[-1] == 's') {
  1010.         if(p[-2] == 'e') {
  1011.             if(p[-3] == 'i') {
  1012.                 if(!strcmp(p-7, "cookies") ||
  1013.                    !strcmp(p-4, "pies"))
  1014.                     goto mins;
  1015.                 Strcpy(p-3, "y");
  1016.                 return bp;
  1017.             }
  1018.  
  1019.             /* note: cloves / knives from clove / knife */
  1020.             if(!strcmp(p-6, "knives")) {
  1021.                 Strcpy(p-3, "fe");
  1022.                 return bp;
  1023.             }
  1024.  
  1025.             if(!strcmp(p-6, "staves")) {
  1026.                 Strcpy(p-3, "ff");
  1027.                 return bp;
  1028.             }
  1029.  
  1030.             /* note: nurses, axes but boxes */
  1031.             if(!strcmp(p-5, "boxes")) {
  1032.                 p[-2] = 0;
  1033.                 return bp;
  1034.             }
  1035.         }
  1036.         /* but don't singularize boots or gloves */
  1037.         else if(!strcmp(p-5, "boots") ||
  1038.             !strcmp(p-6, "gloves"))
  1039.                 return bp;
  1040.     mins:
  1041.         p[-1] = 0;
  1042.     } else {
  1043.         if(!strcmp(p-5, "teeth")) {
  1044.             Strcpy(p-5, "tooth");
  1045.             return bp;
  1046.         }
  1047.         /* here we cannot find the plural suffix */
  1048.     }
  1049.     return bp;
  1050. }
  1051.  
  1052. /* Return something wished for.  If not an object, return &zeroobj; if an error
  1053.  * (no matching object), return (struct obj *)0.  Giving readobjnam() a null
  1054.  * pointer skips the error return and creates a random object instead.
  1055.  */
  1056. struct obj *
  1057. readobjnam(bp)
  1058. register char *bp;
  1059. {
  1060.     register char *p;
  1061.     register int i;
  1062.     register struct obj *otmp;
  1063.     int cnt, spe, spesgn, typ, heavy, blessed, uncursed, halfeaten;
  1064.     int iscursed, ispoisoned, mntmp, contents;
  1065.     int iskey, isnamedbox;
  1066. #ifdef TUTTI_FRUTTI
  1067.     struct fruit *f;
  1068.     int ftype = current_fruit;
  1069.     char fruitbuf[BUFSZ];
  1070.     /* We want to check for fruits last so that, for example, someone
  1071.      * who names their fruit "katana" and wishes for a katana gets a real
  1072.      * one.  But, we have to keep around the old buf since in the meantime
  1073.      * we have deleted "empty", "+6", etc...
  1074.      */
  1075. #endif
  1076.     char let;
  1077.     char *un, *dn, *actualn;
  1078.     char *name=0;
  1079. #ifdef WIZARD
  1080.     int fake=0;
  1081. #endif
  1082.  
  1083.     cnt = spe = spesgn = typ = heavy = blessed = uncursed = iscursed =
  1084.         ispoisoned = halfeaten = iskey = isnamedbox = 0;
  1085.     mntmp = -1;
  1086. #define UNDEFINED 0
  1087. #define EMPTY 1
  1088. #define SPINACH 2
  1089.     contents = UNDEFINED;
  1090.     let = 0;
  1091.     actualn = dn = un = 0;
  1092.     
  1093.     for(;;) {
  1094.         if (!bp) goto any;
  1095.         if(!strncmp(bp, "an ", 3)) {
  1096.             cnt = 1;
  1097.             bp += 3;
  1098.         } else if(!strncmp(bp, "a ", 2)) {
  1099.             cnt = 1;
  1100.             bp += 2;
  1101.         } else if(!strncmp(bp, "cheap plastic imitation of ", 27)) {
  1102. #ifdef WIZARD
  1103.             fake = 1;
  1104. #endif
  1105.             bp += 27;
  1106.         } else if(!strncmp(bp, "the ", 4)){
  1107.     /*        the = 1; */
  1108.             bp += 4;
  1109.         } else if(!cnt && digit(*bp)){
  1110.             cnt = atoi(bp);
  1111.             while(digit(*bp)) bp++;
  1112.             while(*bp == ' ') bp++;
  1113.         } else if(!strncmp(bp, "partly eaten ", 13)) {
  1114.             halfeaten = 1;
  1115.             bp += 13;
  1116.         } else if(!strncmp(bp,"blessed ",8)) {
  1117.             blessed=1;
  1118.             bp += 8;
  1119.         } else if(!strncmp(bp,"holy ",5)) {
  1120.             blessed=1;
  1121.             bp += 5;
  1122.         } else if(!strncmp(bp,"cursed ",7) || !strncmp(bp,"unholy ",7)){
  1123.             iscursed=1;
  1124.             bp += 7;
  1125.         } else if(!strncmp(bp, "uncursed ",9)) {
  1126.             uncursed=1;
  1127.             bp += 9;
  1128.         } else break;
  1129.     }
  1130.     if(!cnt) cnt = 1;        /* %% what with "gems" etc. ? */
  1131. #ifdef TUTTI_FRUTTI
  1132.     Strcpy(fruitbuf, bp);
  1133. #endif
  1134.     if(!strncmp(bp, "empty ", 6)) {
  1135.         contents = EMPTY;
  1136.         bp += 6;
  1137.     } else if(!strncmp(bp, "poisoned ",9)) {
  1138.         ispoisoned=1;
  1139.         bp += 9;
  1140. #ifdef WIZARD
  1141.     } else if(wizard && !strncmp(bp, "trapped ",8)) {
  1142.         ispoisoned=1;
  1143.         bp += 8;
  1144. #endif
  1145.     }
  1146.     if(*bp == '+' || *bp == '-'){
  1147.         spesgn = (*bp++ == '+') ? 1 : -1;
  1148.         spe = atoi(bp);
  1149.         while(digit(*bp)) bp++;
  1150.         while(*bp == ' ') bp++;
  1151.     } else {
  1152.         p = rindex(bp, '(');
  1153.         if(p) {
  1154.             if(p > bp && p[-1] == ' ') p[-1] = 0;
  1155.             else *p = 0;
  1156.             p++;
  1157.             if (!(isnamedbox = named_box(p))) {
  1158.                 spe = atoi(p);
  1159.                 while(digit(*p)) p++;
  1160.                 if (*p != ')') spe = 0;
  1161.                 else {
  1162.                     spesgn = 1;
  1163.                     p++; 
  1164.                     if (*p) Strcat(bp, p);
  1165.                 }
  1166.             }
  1167.         }
  1168.     }
  1169. /*
  1170.    otmp->spe is type schar; so we don't want spe to be any bigger or smaller.
  1171.    also, spe should always be positive  -- some cheaters may try to confuse
  1172.    atoi()
  1173. */
  1174.     if (spe < 0) {
  1175.         spesgn = -1;    /* cheaters get what they deserve */
  1176.         spe = abs(spe);
  1177.     }
  1178.     if (spe > SCHAR_MAX)
  1179.         spe = SCHAR_MAX;
  1180.  
  1181.     /* now we have the actual name, as delivered by xname, say
  1182.         green potions called whisky
  1183.         scrolls labeled "QWERTY"
  1184.         egg
  1185.         fortune cookies
  1186.         very heavy iron ball named hoei
  1187.         wand of wishing
  1188.         elven cloak
  1189.     */
  1190.     for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) {
  1191.         *p = 0;
  1192.         name = p+7;
  1193.     }
  1194.     for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) {
  1195.         *p = 0;
  1196.         un = p+8;
  1197.         /* "helmet called telepathy" is not "helmet" (a specific type)
  1198.          * "shield called reflection" is not "shield" (a general type)
  1199.          */
  1200.         for(i = 0; i < SIZE(o_ranges); i++)
  1201.             if(!strcmp(bp, o_ranges[i].name)) {
  1202.             let = o_ranges[i].osym;
  1203.             goto srch;
  1204.             }
  1205.     }
  1206.     for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) {
  1207.         *p = 0;
  1208.         dn = p+9;
  1209.     }
  1210.     for(p = bp; *p; p++) if(!strncmp(p, " labelled ", 10)) {
  1211.         *p = 0;
  1212.         dn = p+10;
  1213.     }
  1214.     for(p = bp; *p; p++) if(!strncmp(p, " of spinach", 11)) {
  1215.         *p = 0;
  1216.         contents = SPINACH;
  1217.     }
  1218.  
  1219.     /* Skip over "pair of ", then jump to the singular so we don't
  1220.        try to convert "gloves" or "boots". */
  1221.     if(cnt == 1 && !strncmp(bp, "pair of ",8)) {
  1222.         bp += 8;
  1223.         cnt = 2;
  1224.         goto sing;
  1225.         /* cnt is ignored for armor and other non-stackable objects;
  1226.            DTRT for stackable objects */
  1227.     } else if(cnt > 1 && !strncmp(bp, "pairs of ",9)) {
  1228.         bp += 9;
  1229.         cnt *= 2;
  1230.     }
  1231.  
  1232.     /* Find corpse type using "of" (figurine of an orc, tin of orc meat) */
  1233.     for(p = bp; *p; p++)
  1234.         if (!strncmp(p, " of ", 4) && (mntmp = name_to_mon(p+4)) >= 0) {
  1235.             *p = 0;
  1236.             break;
  1237.     }
  1238.     /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
  1239.     if (strncmp(bp, "samurai sword", 13)) /* not the "samurai" monster! */
  1240.     if (strncmp(bp, "wizard lock", 11)) /* not the "wizard" monster! */
  1241.     if (strncmp(bp, "orcish", 6)) /* not the "orc" monster! */
  1242.     if (mntmp < 0) if ((mntmp = name_to_mon(bp)) >= 0) {
  1243.         bp += strlen(mons[mntmp].mname);
  1244.         if (*bp==' ') bp++;
  1245.     }
  1246.  
  1247.     /* first change to singular if necessary */
  1248.     if(cnt != 1 && *bp)
  1249.         Strcpy(bp, makesingular(bp));
  1250.  
  1251. sing:
  1252.     /* Maybe we need a special strcmp() which ignores capitalization and
  1253.      * dashes/spaces/underscores, so some of the below special cases would
  1254.      * be unnecessary.
  1255.      */
  1256.     /* Alternate spellings (two-handed sword vs. two handed sword) */
  1257.     if(!strcmp(bp, "two handed sword")) {
  1258.         typ = TWO_HANDED_SWORD;
  1259.         goto typfnd;
  1260.     }
  1261.     /* pick-axe vs. pick axe */
  1262.     if(!strcmp(bp, "pick axe")) {
  1263.         typ = PICK_AXE;
  1264.         goto typfnd;
  1265.     }
  1266.     if(!strcmp(bp, "luck stone")){
  1267.         typ = LUCKSTONE;
  1268.         goto typfnd;
  1269.     }
  1270.     if(!strcmp(bp, "load stone")){
  1271.         typ = LOADSTONE;
  1272.         goto typfnd;
  1273.     }
  1274.     /* Alternate capitalizations (Amulet of Yendor, amulet of esp) */
  1275.     if(!strcmp(bp, "amulet of Yendor")) {
  1276.         typ = AMULET_OF_YENDOR;
  1277.         goto typfnd;
  1278.     }
  1279.     if(!strcmp(bp, "amulet of ESP")) {
  1280.         typ = AMULET_OF_ESP;
  1281.         goto typfnd;
  1282.     }
  1283.     if(!strcmp(bp, "ring mail") ||    /* Note: ring mail is not a ring ! */
  1284.        !strcmp(bp, "leather armor") || /* Prevent falling to 'armor'. */
  1285.        !strcmp(bp, "studded leather armor")) {
  1286.         let = ARMOR_SYM;
  1287.         actualn = bp;
  1288.         goto srch;
  1289.     }
  1290.     if(!strcmp(bp, "food ration")){
  1291.         let = FOOD_SYM;
  1292.         actualn = bp;
  1293.         goto srch;
  1294.     }
  1295.     if((iskey = named_key(bp)) > 0) {
  1296.         typ = KEY;
  1297.         goto typfnd;
  1298.     }
  1299.     p = eos(bp);
  1300.     if(!strcmp(p-10, "holy water")) {
  1301.         typ = POT_WATER;
  1302.         if (*(p-12) == 'u') iscursed = 1; /* unholy water */
  1303.         else blessed = 1;
  1304.         goto typfnd;
  1305.     }
  1306. #ifdef SHIRT
  1307.     if (!strcmp(p-5, "shirt")) {
  1308.         typ = HAWAIIAN_SHIRT;
  1309.         goto typfnd;
  1310.     }
  1311. #endif
  1312.     if (strlen(bp) == 1 && index(obj_symbols, *bp) && *bp != ILLOBJ_SYM) {
  1313.         let = *bp;
  1314.         goto any;
  1315.     }
  1316.     if(strncmp(bp, "enchant ", 8) &&
  1317.        strncmp(bp, "destroy ", 8) &&
  1318.        strncmp(bp, "food detection", 14))
  1319.     /* allow wishes for "enchant weapon" and "food detection" */
  1320.     for(i = 0; i < sizeof(wrpsym); i++) {
  1321.         register int j = strlen(wrp[i]);
  1322.         if(!strncmp(bp, wrp[i], j)){
  1323.             let = wrpsym[i];
  1324.             if(let != AMULET_SYM) {
  1325.                 bp += j;
  1326.                 if(!strncmp(bp, " of ", 4)) actualn = bp+4;
  1327.                 /* else if(*bp) ?? */
  1328.             } else
  1329.                 actualn = bp;
  1330.             goto srch;
  1331.         }
  1332.         if(!strcmp(p-j, wrp[i])){
  1333.             let = wrpsym[i];
  1334.             p -= j;
  1335.             *p = 0;
  1336.             if(p[-1] == ' ') p[-1] = 0;
  1337.             dn = bp;
  1338.             goto srch;
  1339.         }
  1340.     }
  1341.     if(!strcmp(p-6, " stone")){
  1342.         p[-6] = 0;
  1343.         let = GEM_SYM;
  1344.         dn = actualn = bp;
  1345.         goto srch;
  1346.     }
  1347.     if(!strcmp(p-10, "gold piece") || !strcmp(p-7, "zorkmid") ||
  1348.            !strcmp(bp, "Zorkmid") ||
  1349.            !strcmp(bp, "gold") || !strcmp(bp, "money") || *bp == GOLD_SYM) {
  1350.             if (cnt > 5000
  1351. #ifdef WIZARD
  1352.                     && !wizard
  1353. #endif
  1354.                         ) cnt=5000;
  1355.         if (cnt < 1) cnt=1;
  1356.         pline("%d gold piece%s.", cnt, plur((long)cnt));
  1357.         u.ugold += cnt;
  1358.         flags.botl=1;
  1359.         return (&zeroobj);
  1360.     }
  1361. #ifdef WIZARD
  1362.     /* Let wizards wish for traps --KAA */
  1363.     if (wizard) {
  1364.         int trap;
  1365.         char *tname;
  1366.  
  1367.         for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
  1368.             tname = index(traps[trap], ' ');
  1369.             if (tname) {
  1370.                 if (!strncmp(tname+1, bp, strlen(tname+1))) {
  1371.                     (void) maketrap(u.ux, u.uy, trap);
  1372.                     pline("A%s.", traps[trap]);
  1373.                     if (Invisible) newsym(u.ux,u.uy);
  1374.                     return(&zeroobj);
  1375.                 }
  1376.             }
  1377.         }
  1378.     }
  1379. #endif
  1380.     if(!strcmp(bp, "very heavy iron ball")) {
  1381.         heavy = 1;
  1382.         typ = HEAVY_IRON_BALL;
  1383.         goto typfnd;
  1384.     }
  1385.     for (i = 0; i < SIZE(o_ranges); i++)
  1386.         if(!strcmp(bp, o_ranges[i].name)) {
  1387.         typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
  1388.         goto typfnd;
  1389.         }
  1390.  
  1391.     actualn = bp;
  1392.     if (!dn) dn = actualn; /* ex. "black cap" */
  1393. srch:
  1394.     i = 1;
  1395.     if(let) i = bases[letindex(let)];
  1396.     while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){
  1397.         register const char *zn;
  1398.  
  1399.         if(actualn && (zn = objects[i].oc_name) && !strcmp(actualn, zn)) {
  1400.             typ = i;
  1401.             goto typfnd;
  1402.         }
  1403.         if(dn && (zn = objects[i].oc_descr) && !strcmp(dn, zn)) {
  1404.             typ = i;
  1405.             goto typfnd;
  1406.         }
  1407.         if(un && (zn = objects[i].oc_uname) && !strcmp(un, zn)) {
  1408.             typ = i;
  1409.             goto typfnd;
  1410.         }
  1411.         i++;
  1412.     }
  1413.     if (actualn) {
  1414.         struct Jitem *j = Japanese_items;
  1415.         while(j->item) {
  1416.             if (actualn && !strcmp(actualn, j->name)) {
  1417.                 typ = j->item;
  1418.                 goto typfnd;
  1419.             }
  1420.             j++;
  1421.         }
  1422.     }
  1423. #ifdef TUTTI_FRUTTI
  1424.     for(f=ffruit; f; f = f->nextf) {
  1425.         char *f1 = f->fname, *f2 = makeplural(f->fname);
  1426.  
  1427.         if(!strncmp(fruitbuf, f1, strlen(f1)) ||
  1428.                     !strncmp(fruitbuf, f2, strlen(f2))) {
  1429.             typ = SLIME_MOLD;
  1430.             ftype = f->fid;
  1431.             goto typfnd;
  1432.         }
  1433.     }
  1434. #endif
  1435.     if(!let) return((struct obj *)0);
  1436. any:
  1437.     if(!let) let = wrpsym[rn2(sizeof(wrpsym))];
  1438. typfnd:
  1439.     if(typ) {
  1440.         let = objects[typ].oc_olet;
  1441.         otmp = mksobj(typ,FALSE);
  1442.     } else {
  1443.         otmp = mkobj(let,FALSE);
  1444.         typ = otmp->otyp;
  1445.     }
  1446.  
  1447.     /* venom isn't really an object and can't be wished for; but allow
  1448.      * wizards to wish for it since it's faster than polymorphing and
  1449.      * spitting.
  1450.      */
  1451.     if(otmp->olet==VENOM_SYM) {
  1452. #ifdef WIZARD
  1453.         if (!wizard) {
  1454. #endif
  1455.             free((genericptr_t) otmp);
  1456.             return((struct obj *)0);
  1457. #ifdef WIZARD
  1458.         } else otmp->spe = 1;
  1459. #endif
  1460.     }
  1461.     if(iskey) otmp->spe = (iskey-1);
  1462.     if(isnamedbox && (otmp->otyp==LARGE_BOX || otmp->otyp==CHEST))
  1463.         otmp->spe = (isnamedbox-1);
  1464.  
  1465.     if(cnt > 0 && objects[typ].oc_merge && 
  1466. #ifdef SPELLS
  1467.             let != SPBOOK_SYM &&
  1468. #endif
  1469.         (cnt < rnd(6) ||
  1470. #ifdef WIZARD
  1471.         wizard ||
  1472. #endif
  1473.          (cnt <= 20 &&
  1474.           ((let == WEAPON_SYM && typ <= SHURIKEN) || (typ == ROCK)))))
  1475.             otmp->quan = cnt;
  1476.  
  1477.     if (spesgn == 0) spe = otmp->spe;
  1478. #ifdef WIZARD
  1479.     else if (wizard) /* no alteration to spe */ ;
  1480. #endif
  1481.     else if (let == ARMOR_SYM || let == WEAPON_SYM || typ == PICK_AXE ||
  1482.             typ == UNICORN_HORN ||
  1483.             (let==RING_SYM && objects[typ].oc_charged)) {
  1484.         if(spe > rnd(5) && spe > otmp->spe) spe = 0;
  1485.         if(spe > 2 && Luck < 0) spesgn = -1;
  1486.     } else {
  1487.         if (let == WAND_SYM) {
  1488.             if (spe > 1 && spesgn == -1) spe = 1;
  1489.         } else {
  1490.             if (spe > 0 && spesgn == -1) spe = 0;
  1491.         }
  1492.         if (spe > otmp->spe) spe = otmp->spe;
  1493.     }
  1494.  
  1495.     if (spesgn == -1) spe = -spe;
  1496.  
  1497.     /* set otmp->spe.  This may, or may not, use spe... */
  1498.     switch (typ) {
  1499.         case TIN: if (contents==EMPTY) {
  1500.                 otmp->corpsenm = -1;
  1501.                 otmp->spe = 0;
  1502.             } else if (contents==SPINACH) {
  1503.                 otmp->corpsenm = -1;
  1504.                 otmp->spe = 1;
  1505.             }
  1506.             break;
  1507. #ifdef TUTTI_FRUTTI
  1508.         case SLIME_MOLD: otmp->spe = ftype;
  1509.             /* Fall through */
  1510. #endif
  1511.         case SKELETON_KEY: case KEY: case CHEST: case LARGE_BOX:
  1512.         case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
  1513.             /* otmp->spe already done in mksobj() */
  1514.                 break;
  1515. #ifdef MAIL
  1516.         case SCR_MAIL: otmp->spe = 1; break;
  1517. #endif
  1518.         case AMULET_OF_YENDOR:
  1519. #ifdef WIZARD
  1520.             if (fake || !wizard)
  1521. #endif
  1522.                 otmp->spe = -1;
  1523. #ifdef WIZARD
  1524.             else otmp->spe = 0;
  1525. #endif
  1526.             break;
  1527.         case WAN_WISHING:
  1528. #ifdef WIZARD
  1529.             if (!wizard) {
  1530. #endif
  1531.                 otmp->spe = (rn2(10) ? -1 : 0);
  1532.                 break;
  1533. #ifdef WIZARD
  1534.             }
  1535.             /* fall through (twice), if wizard */
  1536. #endif
  1537.         case MAGIC_LAMP:
  1538. #ifdef WIZARD
  1539.             if (!wizard) {
  1540. #endif
  1541.                 otmp->spe = 0;
  1542.                 break;
  1543. #ifdef WIZARD
  1544.             }
  1545.             /* fall through, if wizard */
  1546. #endif
  1547.         default: otmp->spe = spe;
  1548.     }
  1549.  
  1550.     /* set otmp->corpsenm */
  1551.     if (mntmp > -1) switch(typ) {
  1552.         case TIN:
  1553.             otmp->spe = 0; /* No spinach */
  1554.         case CORPSE:
  1555.             if (!(mons[mntmp].geno & G_NOCORPSE))
  1556.                 otmp->corpsenm = mntmp;
  1557.             break;
  1558.         case FIGURINE:
  1559.             if (!(mons[mntmp].geno & G_UNIQ)
  1560.                 && !is_human(&mons[mntmp]))
  1561.                 otmp->corpsenm = mntmp;
  1562.             break;
  1563.         case EGG: if (lays_eggs(&mons[mntmp]) || mntmp==PM_KILLER_BEE)
  1564.                 otmp->corpsenm = mntmp;
  1565.             break;
  1566.         case STATUE: otmp->corpsenm = mntmp;
  1567.             break;
  1568.         case DRAGON_SCALE_MAIL: /* Not actually possible unless they
  1569.                    typed "red dragon dragon scale mail" */
  1570.         case SCALE_MAIL:
  1571.             if (mntmp >= PM_GRAY_DRAGON &&
  1572.                 mntmp <= PM_YELLOW_DRAGON)
  1573.                 otmp->corpsenm = mntmp;
  1574.             if (otmp->corpsenm >= 0)
  1575.                 otmp->otyp = DRAGON_SCALE_MAIL;
  1576.             break;
  1577.     }
  1578.  
  1579.     /* set blessed/cursed */
  1580.     if (iscursed) {
  1581.         curse(otmp);
  1582.     } else if (uncursed) {
  1583.         otmp->blessed = 0;
  1584.         otmp->cursed = (Luck < 0
  1585. #ifdef WIZARD
  1586.                      && !wizard
  1587. #endif
  1588.                             );
  1589.     } else if (blessed) {
  1590.         otmp->blessed = (Luck >= 0
  1591. #ifdef WIZARD
  1592.                      || wizard
  1593. #endif
  1594.                             );
  1595.         otmp->cursed = (Luck < 0
  1596. #ifdef WIZARD
  1597.                      && !wizard
  1598. #endif
  1599.                             );
  1600.     } else if (spesgn < 0) {
  1601.         curse(otmp);
  1602.     }
  1603.  
  1604.     /* prevent wishing abuse */
  1605.     if (
  1606. #ifdef WIZARD
  1607.         !wizard &&
  1608. #endif
  1609.         (otmp->otyp == WAN_WISHING || otmp->otyp == MAGIC_LAMP))
  1610.         otmp->recharged = 1;
  1611.  
  1612.     /* set poisoned */
  1613.     if (ispoisoned) {
  1614.         if (let == WEAPON_SYM && typ <= SHURIKEN)
  1615.         otmp->opoisoned = (Luck >= 0);
  1616. #ifdef WIZARD
  1617.         else if (Is_box(otmp))
  1618.         otmp->otrapped = 1;
  1619.         else if (let == FOOD_SYM)
  1620.         /* try to taint by making it as old as possible */
  1621.             otmp->age = 1L;
  1622. #endif
  1623.     }
  1624.  
  1625.     if (name) otmp = oname(otmp, name, 0);
  1626.     otmp->owt = weight(otmp);
  1627.     if (heavy) otmp->owt += 15;
  1628.     if (halfeaten && otmp->olet == FOOD_SYM) {
  1629.         if (otmp->otyp == CORPSE)
  1630.             otmp->oeaten = mons[otmp->corpsenm].cnutrit;
  1631.         else otmp->oeaten = objects[otmp->otyp].nutrition;
  1632.         otmp->owt /= 2;
  1633.         otmp->oeaten /= 2;
  1634.         if (!otmp->owt) otmp->owt = 1;
  1635.         if (!otmp->oeaten) otmp->oeaten = 1;
  1636.     }
  1637.     return(otmp);
  1638. }
  1639.  
  1640. int
  1641. rnd_class(first,last)
  1642. int first,last;
  1643. {
  1644.     int i, x, sum=0;
  1645.     for(i=first; i<=last; i++)
  1646.         sum += objects[i].oc_prob;
  1647.     x = rnd(sum);
  1648.     for(i=first; i<=last; i++)
  1649.         if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
  1650.             return i;
  1651.     return 0;
  1652. }
  1653.  
  1654. STATIC_OVL const char *
  1655. Japanese_item_name(i)
  1656. int i;
  1657. {
  1658.     struct Jitem *j = Japanese_items;
  1659.  
  1660.     while(j->item) {
  1661.         if (i == j->item)
  1662.             return j->name;
  1663.         j++;
  1664.     }
  1665.     return (const char *)0;
  1666. }
  1667. #endif /* OVLB */
  1668.